{
 "cells": [
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T05:46:49.082236Z",
     "start_time": "2025-02-27T05:46:35.636550Z"
    }
   },
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "    \n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n",
    "\n",
    "seed = 42\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=12, micro=3, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.0\n",
      "numpy 2.0.2\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.1\n",
      "torch 2.6.0+cu126\n",
      "cuda:0\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数据准备"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T05:46:59.767943Z",
     "start_time": "2025-02-27T05:46:54.138617Z"
    }
   },
   "source": [
    "from torchvision import datasets\n",
    "from torchvision.transforms import ToTensor\n",
    "from torch.utils.data import random_split\n",
    "\n",
    "# fashion_mnist图像分类数据集\n",
    "train_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "test_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=False,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "# torchvision 数据集里没有提供训练集和验证集的划分\n",
    "# 这里用 random_split 按照 11 : 1 的比例来划分数据集\n",
    "train_ds, val_ds = random_split(train_ds, [55000, 5000], torch.Generator().manual_seed(seed))"
   ],
   "outputs": [],
   "execution_count": 2
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T05:47:12.599946Z",
     "start_time": "2025-02-27T05:47:12.596064Z"
    }
   },
   "source": [
    "from torchvision.transforms import Normalize\n",
    "\n",
    "# 遍历train_ds得到每张图片，计算每个通道的均值和方差\n",
    "def cal_mean_std(ds):\n",
    "    mean = 0.\n",
    "    std = 0.\n",
    "    for img, _ in ds:\n",
    "        mean += img.mean(dim=(1, 2))\n",
    "        std += img.std(dim=(1, 2))\n",
    "    mean /= len(ds)\n",
    "    std /= len(ds)\n",
    "    return mean, std\n",
    "\n",
    "\n",
    "# print(cal_mean_std(train_ds))\n",
    "# 0.2860， 0.3205\n",
    "transforms = nn.Sequential(\n",
    "    Normalize([0.2856], [0.3202])\n",
    ") # 对每个通道进行标准化"
   ],
   "outputs": [],
   "execution_count": 3
  },
  {
   "cell_type": "code",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "ExecuteTime": {
     "end_time": "2025-02-27T05:47:13.543623Z",
     "start_time": "2025-02-27T05:47:13.529640Z"
    }
   },
   "source": [
    "img, label = train_ds[0]\n",
    "img.shape, label"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(torch.Size([1, 28, 28]), 9)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 4
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T05:47:14.071523Z",
     "start_time": "2025-02-27T05:47:14.066770Z"
    }
   },
   "source": [
    "from torch.utils.data.dataloader import DataLoader\n",
    "\n",
    "batch_size = 32\n",
    "# 从数据集到dataloader\n",
    "train_loader = DataLoader(train_ds, batch_size=batch_size, shuffle=True, num_workers=4)\n",
    "val_loader = DataLoader(val_ds, batch_size=batch_size, shuffle=False, num_workers=4)\n",
    "test_loader = DataLoader(test_ds, batch_size=batch_size, shuffle=False, num_workers=4)"
   ],
   "outputs": [],
   "execution_count": 5
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义模型"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "ExecuteTime": {
     "end_time": "2025-02-27T05:47:14.949633Z",
     "start_time": "2025-02-27T05:47:14.945605Z"
    }
   },
   "source": [
    "128*9"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1152"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 6
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T05:47:15.254812Z",
     "start_time": "2025-02-27T05:47:15.235848Z"
    }
   },
   "source": [
    "class CNN(nn.Module):\n",
    "    def __init__(self, activation=\"relu\"):\n",
    "        super(CNN, self).__init__()\n",
    "        self.activation = F.relu if activation == \"relu\" else F.selu\n",
    "        #输入通道数，图片是灰度图，所以是1，图片是彩色图，就是3，输出通道数，就是卷积核的个数（32,1,28,28）\n",
    "        #输入x(32,1,28,28) 输出x(32,32,28,28)\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, padding=1)\n",
    "        #输入x(32,32,28,28) 输出x(32,32,28,28)\n",
    "        self.conv2 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, padding=1)\n",
    "        self.pool = nn.MaxPool2d(2, 2) #池化不能够改变通道数，池化核大小为2（2*2），步长为2  (28-2)//2+1=14\n",
    "        self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1)\n",
    "        self.conv4 = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, padding=1)\n",
    "        self.conv5 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=1)\n",
    "        self.conv6 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, padding=1)\n",
    "        self.flatten = nn.Flatten()\n",
    "        # input shape is (28, 28, 1) so the fc1 layer in_features is 128 * 3 * 3\n",
    "        self.fc1 = nn.Linear(128 * 3 * 3, 128)\n",
    "        self.fc2 = nn.Linear(128, 10) #输出尺寸（32,10）\n",
    "\n",
    "        self.init_weights()\n",
    "\n",
    "    def init_weights(self):\n",
    "        \"\"\"使用 xavier 均匀分布来初始化全连接层、卷积层的权重 W\"\"\"\n",
    "        for m in self.modules():\n",
    "            if isinstance(m, (nn.Linear, nn.Conv2d)):\n",
    "                nn.init.xavier_uniform_(m.weight)\n",
    "                nn.init.zeros_(m.bias)\n",
    "\n",
    "    def forward(self, x):\n",
    "        act = self.activation\n",
    "        x = self.pool(act(self.conv2(act(self.conv1(x))))) # 1 * 28 * 28 -> 32 * 14 * 14\n",
    "        # print(x.shape)\n",
    "        x = self.pool(act(self.conv4(act(self.conv3(x))))) # 32 * 14 * 14 -> 64 * 7 * 7\n",
    "        # print(x.shape)\n",
    "        x = self.pool(act(self.conv6(act(self.conv5(x))))) # 64 * 7 * 7 -> 128 * 3 * 3\n",
    "        # print(x.shape)\n",
    "        x = self.flatten(x) # 128 * 3 * 3 ->1152\n",
    "        x = act(self.fc1(x)) # 1152 -> 128\n",
    "        x = self.fc2(x) # 128 -> 10\n",
    "        return x\n",
    "\n",
    "\n",
    "for idx, (key, value) in enumerate(CNN().named_parameters()):\n",
    "    print(f\"{key}\\tparamerters num: {np.prod(value.shape)}\") # 打印模型的参数信息\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "conv1.weight\tparamerters num: 288\n",
      "conv1.bias\tparamerters num: 32\n",
      "conv2.weight\tparamerters num: 9216\n",
      "conv2.bias\tparamerters num: 32\n",
      "conv3.weight\tparamerters num: 18432\n",
      "conv3.bias\tparamerters num: 64\n",
      "conv4.weight\tparamerters num: 36864\n",
      "conv4.bias\tparamerters num: 64\n",
      "conv5.weight\tparamerters num: 73728\n",
      "conv5.bias\tparamerters num: 128\n",
      "conv6.weight\tparamerters num: 147456\n",
      "conv6.bias\tparamerters num: 128\n",
      "fc1.weight\tparamerters num: 147456\n",
      "fc1.bias\tparamerters num: 128\n",
      "fc2.weight\tparamerters num: 1280\n",
      "fc2.bias\tparamerters num: 10\n"
     ]
    }
   ],
   "execution_count": 7
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T05:47:15.941365Z",
     "start_time": "2025-02-27T05:47:15.937218Z"
    }
   },
   "cell_type": "code",
   "source": "3*3*32    *32",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9216"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 8
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T05:47:16.403864Z",
     "start_time": "2025-02-27T05:47:16.400087Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def count_parameters(model): #计算模型总参数量\n",
    "    return sum(p.numel() for p in model.parameters() if p.requires_grad)"
   ],
   "outputs": [],
   "execution_count": 9
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T05:47:16.829614Z",
     "start_time": "2025-02-27T05:47:16.822099Z"
    }
   },
   "cell_type": "code",
   "source": "count_parameters(CNN())",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "435306"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 10
  },
  {
   "cell_type": "code",
   "source": [
    "#练习不同尺寸的卷积核，padding，stride的效果\n",
    "class CNN1(nn.Module):\n",
    "    def __init__(self, activation=\"relu\"):\n",
    "        super().__init__()\n",
    "        self.activation = F.relu if activation == \"relu\" else F.selu\n",
    "        #输入通道数，图片是灰度图，所以是1，图片是彩色图，就是3，输出通道数，就是卷积核的个数（32,1,28,28）\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=5,padding=1,stride=1)\n",
    "        #输入x(32,32,28,28) 输出x(32,32,28,28)\n",
    "        self.conv2 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, padding=1)\n",
    "        self.pool = nn.MaxPool2d(2, 2) #池化核大小为2（2*2），步长为2\n",
    "        self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1)\n",
    "        self.conv4 = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, padding=1)\n",
    "        self.conv5 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=1)\n",
    "        self.conv6 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, padding=1)\n",
    "        self.flatten = nn.Flatten()\n",
    "        # input shape is (28, 28, 1) so the fc1 layer in_features is 128 * 3 * 3\n",
    "        self.fc1 = nn.Linear(128 * 3 * 3, 128)\n",
    "        self.fc2 = nn.Linear(128, 10) #输出尺寸（32,10）\n",
    "\n",
    "        self.init_weights()\n",
    "\n",
    "    def init_weights(self):\n",
    "        \"\"\"使用 xavier 均匀分布来初始化全连接层、卷积层的权重 W\"\"\"\n",
    "        for m in self.modules():\n",
    "            if isinstance(m, (nn.Linear, nn.Conv2d)):\n",
    "                nn.init.xavier_uniform_(m.weight)\n",
    "                nn.init.zeros_(m.bias)\n",
    "\n",
    "    def forward(self, x):\n",
    "        act = self.activation\n",
    "        x=act(self.conv1(x)) # 1 * 28 * 28 -> 32 * 28 * 28\n",
    "        print(x.shape)\n",
    "        # x=act(self.conv2(x)) # 32 * 28 * 28 -> 32 * 28 * 28\n",
    "        # print(x.shape)\n",
    "        # x = self.pool(x) # 32 * 28 * 28 -> 32 * 14 * 14\n",
    "        # print(x.shape)\n",
    "        # x=act(self.conv3(x)) # 32 * 14 * 14 -> 64 * 14 * 14\n",
    "        # print(x.shape)\n",
    "        # x=act(self.conv4(x)) # 64 * 14 * 14 -> 64 * 14 * 14\n",
    "        # print(x.shape)\n",
    "        # x = self.pool(x) # 32 * 14 * 14 -> 64 * 7 * 7\n",
    "        # print(x.shape)\n",
    "        # x=act(self.conv5(x)) # 64 * 7 * 7 -> 128 * 7 * 7\n",
    "        # print(x.shape)\n",
    "        # x=act(self.conv6(x)) # 128 * 7 * 7 -> 128 * 7 * 7\n",
    "        # print(x.shape)\n",
    "        # x = self.pool(x) # 128 * 7 * 7 -> 128 * 3 * 3\n",
    "        # print(x.shape)\n",
    "        # x = self.flatten(x) # 128 * 3 * 3 ->1152\n",
    "        # x = act(self.fc1(x)) # 1152 -> 128\n",
    "        # x = self.fc2(x) # 128 -> 10\n",
    "        return x\n",
    "activation = \"relu\"\n",
    "model = CNN1(activation)\n",
    "# model.to(device)\n",
    "img = torch.randn(1, 1, 28, 28)\n",
    "model(img)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-02-27T05:47:17.296957Z",
     "start_time": "2025-02-27T05:47:17.260778Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([1, 32, 26, 26])\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "tensor([[[[0.0000, 0.0000, 0.0000,  ..., 0.1525, 0.0000, 0.1096],\n",
       "          [0.0223, 0.0000, 0.0000,  ..., 0.0000, 0.2388, 0.1966],\n",
       "          [0.0000, 0.1055, 0.0000,  ..., 0.1410, 0.0000, 0.2367],\n",
       "          ...,\n",
       "          [0.1567, 0.0000, 0.0000,  ..., 0.0000, 0.3064, 0.1214],\n",
       "          [0.0000, 0.0000, 0.0000,  ..., 0.0609, 0.0885, 0.1430],\n",
       "          [0.4755, 0.0000, 0.0000,  ..., 0.0144, 0.0000, 0.5107]],\n",
       "\n",
       "         [[0.0000, 0.0000, 0.0000,  ..., 0.0816, 0.0000, 0.3483],\n",
       "          [0.0000, 0.0000, 0.0311,  ..., 0.0000, 0.0000, 0.0000],\n",
       "          [0.0000, 0.0000, 0.0000,  ..., 0.1699, 0.0736, 0.0000],\n",
       "          ...,\n",
       "          [0.0000, 0.0000, 0.0477,  ..., 0.1474, 0.3227, 0.0000],\n",
       "          [0.0000, 0.1636, 0.0000,  ..., 0.0000, 0.3399, 0.1678],\n",
       "          [0.0000, 0.0975, 0.1223,  ..., 0.3508, 0.0266, 0.0784]],\n",
       "\n",
       "         [[0.0776, 0.0000, 0.2568,  ..., 0.0000, 0.0136, 0.1062],\n",
       "          [0.0054, 0.0348, 0.0000,  ..., 0.2418, 0.0000, 0.3137],\n",
       "          [0.0000, 0.0000, 0.1545,  ..., 0.0000, 0.2764, 0.0000],\n",
       "          ...,\n",
       "          [0.1332, 0.0571, 0.0252,  ..., 0.0000, 0.0766, 0.2786],\n",
       "          [0.3616, 0.0000, 0.4619,  ..., 0.0000, 0.2689, 0.1045],\n",
       "          [0.0000, 0.1184, 0.2616,  ..., 0.0350, 0.0000, 0.0000]],\n",
       "\n",
       "         ...,\n",
       "\n",
       "         [[0.0589, 0.0000, 0.0000,  ..., 0.0000, 0.0000, 0.0190],\n",
       "          [0.0000, 0.0000, 0.0000,  ..., 0.0000, 0.0000, 0.0000],\n",
       "          [0.0000, 0.0000, 0.0000,  ..., 0.0000, 0.0000, 0.0557],\n",
       "          ...,\n",
       "          [0.0000, 0.1270, 0.1526,  ..., 0.1875, 0.1466, 0.3250],\n",
       "          [0.0211, 0.1985, 0.0000,  ..., 0.0000, 0.1375, 0.0000],\n",
       "          [0.0221, 0.0000, 0.1786,  ..., 0.0516, 0.2037, 0.0000]],\n",
       "\n",
       "         [[0.0000, 0.1064, 0.0737,  ..., 0.0000, 0.4167, 0.0000],\n",
       "          [0.0000, 0.2331, 0.0000,  ..., 0.0000, 0.0000, 0.0000],\n",
       "          [0.0000, 0.0000, 0.2401,  ..., 0.0490, 0.2213, 0.0000],\n",
       "          ...,\n",
       "          [0.0000, 0.1145, 0.0000,  ..., 0.3371, 0.0459, 0.0000],\n",
       "          [0.3806, 0.0000, 0.0037,  ..., 0.0000, 0.3291, 0.0000],\n",
       "          [0.0000, 0.1750, 0.3379,  ..., 0.0849, 0.0000, 0.0000]],\n",
       "\n",
       "         [[0.0692, 0.1059, 0.0537,  ..., 0.2263, 0.2132, 0.0923],\n",
       "          [0.0435, 0.0000, 0.0000,  ..., 0.1021, 0.0000, 0.3301],\n",
       "          [0.0000, 0.0000, 0.1516,  ..., 0.0000, 0.0015, 0.0000],\n",
       "          ...,\n",
       "          [0.0000, 0.0000, 0.1263,  ..., 0.0091, 0.0737, 0.0000],\n",
       "          [0.0619, 0.0000, 0.1354,  ..., 0.0000, 0.2505, 0.0000],\n",
       "          [0.0973, 0.0499, 0.0000,  ..., 0.0446, 0.1009, 0.1469]]]],\n",
       "       grad_fn=<ReluBackward0>)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 11
  },
  {
   "cell_type": "code",
   "source": "",
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-02-27T05:47:17.880475Z",
     "start_time": "2025-02-27T05:47:17.877967Z"
    }
   },
   "outputs": [],
   "execution_count": 11
  },
  {
   "cell_type": "code",
   "source": [
    "\n",
    "class CNN2(nn.Module):\n",
    "    def __init__(self, activation=\"relu\"):\n",
    "        super(CNN, self).__init__()\n",
    "        self.activation = F.relu if activation == \"relu\" else F.selu\n",
    "        #输入通道数，图片是灰度图，所以是1，图片是彩色图，就是3，输出通道数，就是卷积核的个数（32,1,28,28）\n",
    "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, padding=1)\n",
    "        #输入x(32,32,28,28) 输出x(32,32,28,28)\n",
    "        self.conv2 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, padding=1)\n",
    "        self.pool = nn.MaxPool2d(2, 2) #池化核大小为2（2*2），步长为2\n",
    "        self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1)\n",
    "        self.conv4 = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, padding=1)\n",
    "        self.conv5 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=1)\n",
    "        self.conv6 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, padding=1)\n",
    "        self.flatten = nn.Flatten()\n",
    "        # input shape is (28, 28, 1) so the fc1 layer in_features is 128 * 3 * 3\n",
    "        self.fc1 = nn.Linear(128 * 3 * 3, 128)\n",
    "        self.fc2 = nn.Linear(128, 10) #输出尺寸（32,10）\n",
    "\n",
    "        self.init_weights()\n",
    "\n",
    "    def init_weights(self):\n",
    "        \"\"\"使用 xavier 均匀分布来初始化全连接层、卷积层的权重 W\"\"\"\n",
    "        for m in self.modules():\n",
    "            if isinstance(m, (nn.Linear, nn.Conv2d)):\n",
    "                nn.init.xavier_uniform_(m.weight)\n",
    "                nn.init.zeros_(m.bias)\n",
    "\n",
    "    def forward(self, x):\n",
    "        act = self.activation\n",
    "        x=act(self.conv1(x)) # 1 * 28 * 28 -> 32 * 28 * 28\n",
    "        print(x.shape)\n",
    "        x=act(self.conv2(x)) # 32 * 28 * 28 -> 32 * 28 * 28\n",
    "        print(x.shape)\n",
    "        x = self.pool(x) # 32 * 28 * 28 -> 32 * 14 * 14\n",
    "        print(x.shape)\n",
    "        x=act(self.conv3(x)) # 32 * 14 * 14 -> 64 * 14 * 14\n",
    "        print(x.shape)\n",
    "        x=act(self.conv4(x)) # 64 * 14 * 14 -> 64 * 14 * 14\n",
    "        print(x.shape)\n",
    "        x = self.pool(x) # 32 * 14 * 14 -> 64 * 7 * 7\n",
    "        print(x.shape)\n",
    "        x=act(self.conv5(x)) # 64 * 7 * 7 -> 128 * 7 * 7\n",
    "        print(x.shape)\n",
    "        x=act(self.conv6(x)) # 128 * 7 * 7 -> 128 * 7 * 7\n",
    "        print(x.shape)\n",
    "        x = self.pool(x) # 128 * 7 * 7 -> 128 * 3 * 3\n",
    "        print(x.shape)\n",
    "        x = self.flatten(x) # 128 * 3 * 3 ->1152\n",
    "        x = act(self.fc1(x)) # 1152 -> 128\n",
    "        x = self.fc2(x) # 128 -> 10\n",
    "        return x\n",
    "\n",
    "\n",
    "for idx, (key, value) in enumerate(CNN().named_parameters()):\n",
    "    print(f\"{key}\\tparamerters num: {np.prod(value.shape)}\") # 打印模型的参数信息\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-02-27T05:47:18.444126Z",
     "start_time": "2025-02-27T05:47:18.432805Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "conv1.weight\tparamerters num: 288\n",
      "conv1.bias\tparamerters num: 32\n",
      "conv2.weight\tparamerters num: 9216\n",
      "conv2.bias\tparamerters num: 32\n",
      "conv3.weight\tparamerters num: 18432\n",
      "conv3.bias\tparamerters num: 64\n",
      "conv4.weight\tparamerters num: 36864\n",
      "conv4.bias\tparamerters num: 64\n",
      "conv5.weight\tparamerters num: 73728\n",
      "conv5.bias\tparamerters num: 128\n",
      "conv6.weight\tparamerters num: 147456\n",
      "conv6.bias\tparamerters num: 128\n",
      "fc1.weight\tparamerters num: 147456\n",
      "fc1.bias\tparamerters num: 128\n",
      "fc2.weight\tparamerters num: 1280\n",
      "fc2.bias\tparamerters num: 10\n"
     ]
    }
   ],
   "execution_count": 12
  },
  {
   "cell_type": "code",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "ExecuteTime": {
     "end_time": "2025-02-27T05:47:19.255416Z",
     "start_time": "2025-02-27T05:47:19.248415Z"
    }
   },
   "source": [
    "activation = \"relu\"\n",
    "model = CNN(activation)\n",
    "# model.to(device)\n",
    "# img = torch.randn(1, 1, 28, 28)\n",
    "# model(img)"
   ],
   "outputs": [],
   "execution_count": 13
  },
  {
   "cell_type": "code",
   "source": [
    "from torchviz import make_dot\n",
    "\n",
    "# Assuming your model is already defined and named 'model'\n",
    "# Construct a dummy input\n",
    "dummy_input = torch.randn(1, 1, 28, 28)  # Replace with your input shape\n",
    "\n",
    "# Forward pass to generate the computation graph\n",
    "output = model(dummy_input)\n",
    "\n",
    "# Visualize the model architecture\n",
    "dot = make_dot(output, params=dict(model.named_parameters()))\n",
    "dot.render(\"model_CNN\", format=\"png\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-02-27T06:24:10.368229Z",
     "start_time": "2025-02-27T06:24:09.327964Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'model_CNN.png'"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 14
  },
  {
   "cell_type": "code",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "ExecuteTime": {
     "end_time": "2025-02-27T06:26:32.279784Z",
     "start_time": "2025-02-27T06:26:32.274714Z"
    }
   },
   "source": [
    "#计算参数量\n",
    "print(f'conv1 - {1*3*3*32}') # 32个卷积核，每个卷积核大小为1*3*3\n",
    "print(f'conv2 - {32*3*3*32}') # 32个卷积核，每个卷积核大小为32*3*3\n",
    "print(f'conv3 - {32*3*3*64}')\n",
    "print(f'conv4 - {64*3*3*64}')\n",
    "print(f'conv5 - {64*3*3*128}')\n",
    "print(f'conv6 - {128*3*3*128}')\n",
    "print(f'fc1 - {1152*128}')\n",
    "print(f'fc2 - {128*10}')\n",
    "\n",
    "#对上面求和，总参数数目为：\n",
    "1*3*3*32 +32+ 32*3*3*32 +32+ 32*3*3*64 +64+ 64*3*3*64+64 + 64*3*3*128 +128+ 128*3*3*128 +128+ 128*3*3*128+128 + 128*10+10"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "conv1 - 288\n",
      "conv2 - 9216\n",
      "conv3 - 18432\n",
      "conv4 - 36864\n",
      "conv5 - 73728\n",
      "conv6 - 147456\n",
      "fc1 - 147456\n",
      "fc2 - 1280\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "435306"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 15
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练\n",
    "\n",
    "pytorch的训练需要自行实现，包括\n",
    "1. 定义损失函数\n",
    "2. 定义优化器\n",
    "3. 定义训练步\n",
    "4. 训练"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T06:26:48.211483Z",
     "start_time": "2025-02-27T06:26:47.840665Z"
    }
   },
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "@torch.no_grad()\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = []\n",
    "    pred_list = []\n",
    "    label_list = []\n",
    "    for datas, labels in dataloader:\n",
    "        datas = datas.to(device)\n",
    "        labels = labels.to(device)\n",
    "        # 前向计算\n",
    "        logits = model(datas)              # 验证集预测\n",
    "        loss = loss_fct(logits, labels)         # 验证集损失\n",
    "        loss_list.append(loss.item()) # 将验证集损失加入列表\n",
    "        \n",
    "        preds = logits.argmax(axis=-1)    # 验证集预测\n",
    "        pred_list.extend(preds.cpu().numpy().tolist()) # 将验证集预测结果加入列表\n",
    "        label_list.extend(labels.cpu().numpy().tolist())# 将验证集真实标签加入列表\n",
    "        \n",
    "    acc = accuracy_score(label_list, pred_list) # 计算验证集准确率\n",
    "    return np.mean(loss_list), acc # 返回验证集损失均值和准确率\n"
   ],
   "outputs": [],
   "execution_count": 16
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### TensorBoard 可视化\n",
    "\n",
    "\n",
    "训练过程中可以使用如下命令启动tensorboard服务。\n",
    "\n",
    "```shell\n",
    "tensorboard \\\n",
    "    --logdir=runs \\     # log 存放路径\n",
    "    --host 0.0.0.0 \\    # ip\n",
    "    --port 8848         # 端口\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T06:26:56.168293Z",
     "start_time": "2025-02-27T06:26:51.169923Z"
    }
   },
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "\n",
    "\n",
    "class TensorBoardCallback:\n",
    "    def __init__(self, log_dir, flush_secs=10):\n",
    "        \"\"\"\n",
    "        Args:\n",
    "            log_dir (str): dir to write log.\n",
    "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
    "        \"\"\"\n",
    "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
    "\n",
    "    def draw_model(self, model, input_shape):\n",
    "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
    "        \n",
    "    def add_loss_scalars(self, step, loss, val_loss):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/loss\", \n",
    "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
    "            global_step=step,\n",
    "            )\n",
    "        \n",
    "    def add_acc_scalars(self, step, acc, val_acc):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/accuracy\",\n",
    "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
    "            global_step=step,\n",
    "        )\n",
    "        \n",
    "    def add_lr_scalars(self, step, learning_rate):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/learning_rate\",\n",
    "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
    "            global_step=step,\n",
    "            \n",
    "        )\n",
    "    \n",
    "    def __call__(self, step, **kwargs):\n",
    "        # add loss\n",
    "        loss = kwargs.pop(\"loss\", None)\n",
    "        val_loss = kwargs.pop(\"val_loss\", None)\n",
    "        if loss is not None and val_loss is not None:\n",
    "            self.add_loss_scalars(step, loss, val_loss)\n",
    "        # add acc\n",
    "        acc = kwargs.pop(\"acc\", None)\n",
    "        val_acc = kwargs.pop(\"val_acc\", None)\n",
    "        if acc is not None and val_acc is not None:\n",
    "            self.add_acc_scalars(step, acc, val_acc)\n",
    "        # add lr\n",
    "        learning_rate = kwargs.pop(\"lr\", None)\n",
    "        if learning_rate is not None:\n",
    "            self.add_lr_scalars(step, learning_rate)\n"
   ],
   "outputs": [],
   "execution_count": 17
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save Best\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T06:26:56.944425Z",
     "start_time": "2025-02-27T06:26:56.940355Z"
    }
   },
   "source": [
    "class SaveCheckpointsCallback:\n",
    "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
    "        \"\"\"\n",
    "        Save checkpoints each save_epoch epoch. \n",
    "        We save checkpoint by epoch in this implementation.\n",
    "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
    "\n",
    "        Args:\n",
    "            save_dir (str): dir to save checkpoint\n",
    "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
    "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
    "        \"\"\"\n",
    "        self.save_dir = save_dir\n",
    "        self.save_step = save_step\n",
    "        self.save_best_only = save_best_only\n",
    "        self.best_metrics = -1\n",
    "        \n",
    "        # mkdir\n",
    "        if not os.path.exists(self.save_dir):\n",
    "            os.mkdir(self.save_dir)\n",
    "        \n",
    "    def __call__(self, step, state_dict, metric=None):\n",
    "        if step % self.save_step > 0:\n",
    "            return\n",
    "        \n",
    "        if self.save_best_only:\n",
    "            assert metric is not None\n",
    "            if metric >= self.best_metrics:\n",
    "                # save checkpoints\n",
    "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
    "                # update best metrics\n",
    "                self.best_metrics = metric\n",
    "        else:\n",
    "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
    "\n"
   ],
   "outputs": [],
   "execution_count": 18
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Early Stop"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T06:26:58.645408Z",
     "start_time": "2025-02-27T06:26:58.640157Z"
    }
   },
   "source": [
    "class EarlyStopCallback:\n",
    "    def __init__(self, patience=5, min_delta=0.01):\n",
    "        \"\"\"\n",
    "\n",
    "        Args:\n",
    "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
    "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute \n",
    "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
    "        \"\"\"\n",
    "        self.patience = patience\n",
    "        self.min_delta = min_delta\n",
    "        self.best_metric = -1\n",
    "        self.counter = 0\n",
    "        \n",
    "    def __call__(self, metric):\n",
    "        if metric >= self.best_metric + self.min_delta:\n",
    "            # update best metric\n",
    "            self.best_metric = metric\n",
    "            # reset counter \n",
    "            self.counter = 0\n",
    "        else: \n",
    "            self.counter += 1\n",
    "            \n",
    "    @property\n",
    "    def early_stop(self):\n",
    "        return self.counter >= self.patience\n"
   ],
   "outputs": [],
   "execution_count": 19
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T06:27:12.317639Z",
     "start_time": "2025-02-27T06:27:12.034737Z"
    }
   },
   "source": [
    "# 训练\n",
    "def training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=None,\n",
    "    early_stop_callback=None,\n",
    "    eval_step=500,\n",
    "    ):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "    \n",
    "    global_step = 0\n",
    "    model.train()\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
    "        for epoch_id in range(epoch):\n",
    "            # training\n",
    "            for datas, labels in train_loader:\n",
    "                datas = datas.to(device)\n",
    "                labels = labels.to(device)\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "                # 模型前向计算\n",
    "                logits = model(datas)\n",
    "                # 计算损失\n",
    "                loss = loss_fct(logits, labels)\n",
    "                # 梯度回传\n",
    "                loss.backward()\n",
    "                # 调整优化器，包括学习率的变动等\n",
    "                optimizer.step()\n",
    "                preds = logits.argmax(axis=-1)\n",
    "            \n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())    \n",
    "                loss = loss.cpu().item()\n",
    "                # record\n",
    "                \n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
    "                })\n",
    "                \n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval()\n",
    "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
    "                    })\n",
    "                    model.train()\n",
    "                    \n",
    "                    # 1. 使用 tensorboard 可视化\n",
    "                    if tensorboard_callback is not None:\n",
    "                        tensorboard_callback(\n",
    "                            global_step, \n",
    "                            loss=loss, val_loss=val_loss,\n",
    "                            acc=acc, val_acc=val_acc,\n",
    "                            lr=optimizer.param_groups[0][\"lr\"],\n",
    "                            )\n",
    "                    \n",
    "                    # 2. 保存模型权重 save model checkpoint\n",
    "                    if save_ckpt_callback is not None:\n",
    "                        save_ckpt_callback(global_step, model.state_dict(), metric=val_acc)\n",
    "\n",
    "                    # 3. 早停 Early Stop\n",
    "                    if early_stop_callback is not None:\n",
    "                        early_stop_callback(val_acc)\n",
    "                        if early_stop_callback.early_stop:\n",
    "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
    "                            return record_dict\n",
    "                    \n",
    "                # udate step\n",
    "                global_step += 1\n",
    "                pbar.update(1)\n",
    "                pbar.set_postfix({\"epoch\": epoch_id})\n",
    "        \n",
    "    return record_dict\n",
    "        \n",
    "\n",
    "epoch = 20\n",
    "\n",
    "activation = \"relu\"\n",
    "model = CNN(activation)\n",
    "\n",
    "# 1. 定义损失函数 采用交叉熵损失\n",
    "loss_fct = nn.CrossEntropyLoss()\n",
    "# 2. 定义优化器 采用SGD\n",
    "# Optimizers specified in the torch.optim package\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n",
    "\n",
    "# 1. tensorboard 可视化\n",
    "if not os.path.exists(\"runs\"):\n",
    "    os.mkdir(\"runs\")\n",
    "tensorboard_callback = TensorBoardCallback(f\"runs/cnn-{activation}\")\n",
    "tensorboard_callback.draw_model(model, [1, 1, 28, 28])\n",
    "# 2. save best\n",
    "if not os.path.exists(\"checkpoints\"):\n",
    "    os.makedirs(\"checkpoints\")\n",
    "save_ckpt_callback = SaveCheckpointsCallback(f\"checkpoints/cnn-{activation}\", save_best_only=True)\n",
    "# 3. early stop\n",
    "early_stop_callback = EarlyStopCallback(patience=10)\n",
    "\n"
   ],
   "outputs": [],
   "execution_count": 20
  },
  {
   "cell_type": "code",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "ExecuteTime": {
     "end_time": "2025-02-27T06:35:12.020778Z",
     "start_time": "2025-02-27T06:27:43.785728Z"
    }
   },
   "source": [
    "model = model.to(device)\n",
    "record = training(\n",
    "    model,\n",
    "    train_loader,\n",
    "    val_loader,\n",
    "    epoch,\n",
    "    loss_fct,\n",
    "    optimizer,\n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=save_ckpt_callback,\n",
    "    early_stop_callback=early_stop_callback,\n",
    "    eval_step=1000\n",
    "    )"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "  0%|          | 0/34380 [00:00<?, ?it/s]"
      ],
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "4e2e65dff5a24e408ed572cf3ee4cb58"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Early stop at epoch 13 / global_step 23000\n"
     ]
    }
   ],
   "execution_count": 21
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T06:35:20.512450Z",
     "start_time": "2025-02-27T06:35:20.292812Z"
    }
   },
   "source": [
    "#画线要注意的是损失是不一定在零到1之间的\n",
    "def plot_learning_curves(record_dict, sample_step=500):\n",
    "    # build DataFrame\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "\n",
    "    # plot\n",
    "    fig_num = len(train_df.columns)\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):    \n",
    "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
    "        axs[idx].grid()\n",
    "        axs[idx].legend()\n",
    "        axs[idx].set_xticks(range(0, train_df.index[-1], 5000))\n",
    "        axs[idx].set_xticklabels(map(lambda x: f\"{int(x/1000)}k\", range(0, train_df.index[-1], 5000)))\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "    \n",
    "    plt.show()\n",
    "\n",
    "plot_learning_curves(record, sample_step=500)  #横坐标是 steps"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ],
      "image/png": "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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 22
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 评估"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-27T06:35:32.086376Z",
     "start_time": "2025-02-27T06:35:26.191959Z"
    }
   },
   "source": [
    "# dataload for evaluating\n",
    "\n",
    "# load checkpoints\n",
    "model.load_state_dict(torch.load(f\"checkpoints/cnn-{activation}/best.ckpt\", map_location=\"cpu\"))\n",
    "\n",
    "model.eval()\n",
    "loss, acc = evaluating(model, test_loader, loss_fct)\n",
    "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss:     0.3074\n",
      "accuracy: 0.8895\n"
     ]
    }
   ],
   "execution_count": 23
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": ""
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
